﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// CancelEventArgs
using System.ComponentModel;

/**
 * Make sure that you have added references to Visifire assembly, 
 * WPFVisifire.Charts.dll. Do not forget to include the Visifire.Charts 
 * and Visifire.Commons within any code file where you want to work 
 * with the charts. These files can be added with following syntax:
 * */
using Visifire.Charts;
using Visifire.Commons;

using GasData;

/*For observable collection */
using System.Collections.ObjectModel;

/* Threading */
/* Synchronized methods */
using System.Threading;
using System.Runtime.CompilerServices;

using WebRequestExample;

/* Ntp client to get UTC time */
using MFToolkit.Net.Ntp;

using System.IO;

namespace WPF_DataLogger
{
    //One data point
    //Note any data point to the Visifire should implement
    // the InotifyPropertyChanged interface
    public class GasDataPoint : INotifyPropertyChanged
    {
        public GasDataPoint(DateTime date_time, Double value)
        {
            //First Format Date
            FormatTime(date_time);
            _y_value = value;
        }

        public GasDataPoint(String date_time, Double value)
        {
            _datetime = date_time;
            _y_value = value;
        }

        public void FormatTime(DateTime date_time)
        {
            _datetime = String.Format("{0:g}", date_time);  // "3/9/2008 4:05 PM" ShortDate+ShortTime
        }

        public String Time
        {
            get
            {
                return _datetime;
            }
            set
            {
                _datetime = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Time"));
            }
        }

        public Double YValue
        {
            get
            {
                return _y_value;
            }
            set
            {
                _y_value = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("YValue"));
            }
        }

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        Double _y_value;
        String _datetime;
    }

    //One data series
    public class GasDataSeries
    {
        public GasDataSeries(String series_name)
        {
            _seriesName = series_name;
            _dataPoints = new ObservableCollection<GasDataPoint>();
        }

        public void AddDataPointEntry(GasDataPoint new_point)
        {
            _dataPoints.Add(new_point);
        }

        public String SeriesName
        {
            get
            {
                return _seriesName;
            }
            set
            {
                _seriesName = value;
            }
        }

        public void Cleanup()
        {
            _dataPoints.Clear();
        }

        public ObservableCollection<GasDataPoint> DataPoints
        {
            get
            {
                return _dataPoints;
            }
        }
        private String _seriesName;
        private ObservableCollection<GasDataPoint> _dataPoints;
    }

    class ArchiveParser
    {
        private String _filePath;

        private List<GasDataSeries> _dataSeries;

        public ArchiveParser(String filePath)
        {
            //_file_path = file_name;
            _filePath = filePath;
            _dataSeries = new List<GasDataSeries>();
        }

        public ArchiveParser()
        {
            _dataSeries = new List<GasDataSeries>();
        }

        //Clear all system resources used
        public void Clear()
        {
            foreach (GasDataSeries curve in _dataSeries)
            {
                curve.Cleanup();
            }

            _dataSeries.Clear();
        }

        public bool LoadArchive()
        {
            //Now the file is opened
            if (!System.IO.File.Exists(_filePath))
            {
                MessageBox.Show("No archive data found", 
                    "Loading Archive", MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }
             //Get a list of gases
             //Read double
             //Read time as string
            try
            {
                using (StreamReader file_reader = new StreamReader(_filePath))
                {
                    //First read the list of gas names
                    string[] name_list = null;

                    if (file_reader.Peek() > 0)
                    {
                        string sensors = file_reader.ReadLine();
                        sensors.Trim();
                        char[] delimiters = { ' ' };

                        name_list = sensors.Split(delimiters);
                        CreateSeries(name_list);
                    }

                    while (file_reader.Peek() > 0)
                    {
                        string sensor_values = file_reader.ReadLine();
                        string[] value_list = sensor_values.Split(' ');

                        int idx = 0;
                        string time = "";

                        List<Double> sensorValueList = new List<Double>();

                        foreach (string value_str in value_list)
                        {

                            //First read sensor readings
                            if (value_str != "" && idx < _dataSeries.Count)
                            {
                                double value = Convert.ToDouble(value_str);
                                System.Console.WriteLine("Value: " + value);

                                sensorValueList.Add(Convert.ToDouble(value_str));
                                idx++; //Move to next series;
                            }
                            //Now merge all the time strings
                            else if (value_str != "" && idx >= _dataSeries.Count)
                            {
                                time += value_str + " ";
                            }
                        }

                        time.Trim();
                        for (int i = 0; i < _dataSeries.Count; i++)
                        {
                            GasDataPoint new_point = new GasDataPoint(
                                       time, sensorValueList[i]);
                            _dataSeries[i].AddDataPointEntry(new_point);
                        }

                        System.Console.WriteLine("idx: " + idx);
                    }

                    file_reader.Close();
                }
            }
            catch (IOException ex)
            {
                MessageBox.Show(ex.Message + "Archive is being written, try again later",
                    "Archive is being written",MessageBoxButton.OK,MessageBoxImage.Information);
                return false;
            }

            return true;

        }

        //pre name_list is not null;
        private void CreateSeries(String [] name_list)
        {
            foreach (string sensor_name in name_list)
            {

                GasDataSeries new_series = new GasDataSeries(sensor_name);

                if (sensor_name != "" && NotRepeatedSeries(sensor_name))
                {
                    System.Console.WriteLine("Archiver: " + sensor_name);

                    _dataSeries.Add(new_series);
                }
            }
        }

        private bool NotRepeatedSeries(string series_name)
        {
            foreach (GasDataSeries mySeries in _dataSeries)
            {
                if (mySeries.SeriesName == series_name)
                    return false;
            }

            return true;
        }

        public ObservableCollection<GasDataPoint> GetOneSeriesDataPoints(int idx)
        {
            return _dataSeries[idx].DataPoints;
        }

        public string GetSeriesName(int idx)
        {
            return _dataSeries[idx].SeriesName;
        }
    }
}
